package com.harmonyos.cases.utils;

import com.harmonyos.cases.bean.code.ETSMethodInfo;
import com.harmonyos.cases.bean.code.MethodBlockLocation;

import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.harmonyos.cases.bean.code.ETSMethodInfo.KEY_RETURN;
import static com.harmonyos.cases.bean.code.ETSMethodInfo.KEY_VOID;

/**
 * ets文件解析
 */
public class EtsParser {
    // ets文本
    private String etsText;

    public EtsParser(String etsText) {
        this.etsText = etsText;
    }

    public void setEtsText(String etsText) {
        this.etsText = etsText;
    }

    /**
     * 插入代码
     *
     * @param fileType       插入的文件类型，Ability或者自定义组件
     * @param methodName     需要插入代码的方法
     * @param position       插入代码的方法内的位置，方法头部或者尾部
     * @param code           需要插入的代码
     * @param offsetPosition 光标位置
     * @return 新的文件内容
     */
    public String insertCodeInMethod(ETSMethodInfo.FileType fileType, String methodName, ETSMethodInfo.MethodInnerPosition position, String code, int offsetPosition) {
        if (etsText.trim().contains(code.trim())) {
            return null;
        }
        String newContent = "";
        String start = "";
        String end = "";
        if (methodName.isEmpty()) {
            if (fileType == ETSMethodInfo.FileType.Ability) {
                MethodBlockLocation temp = abilityBlockLocation("export default class");
                if (temp.isEmpty()) {
                    return null;
                }
                String regex = "import\\s+\\{\\s*([a-zA-Z0-9_$\\s,]+)\\s*\\}\\s+from\\s+['\"]([a-zA-Z0-9_\\-\\/.]+)['\"];";

                if (code.contains("import")) {
                    Pattern pattern = Pattern.compile(regex);
                    Matcher matcher = pattern.matcher(etsText);
                    int lastIndex = 0;
                    while (matcher.find()) {
                        lastIndex = matcher.end();
                    }
                    // 如果找到import代码，则添加一个换行符
                    if (lastIndex != 0) {
                        code = "\n" + code;
                    }
                    // 如果没有找到import，则判断文件是否有版权头，有则放在版权头之后
                    if (lastIndex == 0) {
                        if (etsText.startsWith("/*") || etsText.startsWith("/**")) {
                            lastIndex = etsText.indexOf("*/") + 2;
                        }
                    }
                    start = etsText.substring(0, lastIndex);
                    end = etsText.substring(lastIndex);
                } else {
                    start = etsText.substring(0, temp.getStartPosition());
                    end = etsText.substring(temp.getStartPosition() + 1);
                }
                newContent = start + "\n" + code + "\n" + end;
            }
            if (fileType == ETSMethodInfo.FileType.Component) {
                start = etsText.substring(0, offsetPosition);
                end = etsText.substring(offsetPosition);
                newContent = start + "\n" + code + "\n" + end;
            }
            return newContent;
        }
        MethodBlockLocation location = methodBlockPosition(methodName);

        if (location.isEmpty()) {
            String methodInfo = ETSMethodInfo.methodInfo(fileType, methodName);
            if (code.contains("await")) {
                String[] temp = methodInfo.split(":");
                temp[1] = "Promise<" + methodInfo.split(":")[1].trim() + ">";
                methodInfo = temp[0] + ":" + temp[1];
                methodInfo = "async " + methodInfo;
            }
            String insertCode = "";
            if (methodInfo != null) {
                String returnClass = methodInfo.substring(methodInfo.lastIndexOf(":") + 1);
                if (!returnClass.trim().contains(KEY_VOID)) {
                    insertCode = methodInfo + ETSMethodInfo.DEFAULT_METHOD_BLOCK_RETURN;
                } else {
                    insertCode = methodInfo + ETSMethodInfo.DEFAULT_METHOD_BLOCK;
                }
            }
            code = insertCode.replace(ETSMethodInfo.DEFAULT_REPLACE, code);
            if (offsetPosition != -1) {
                start = etsText.substring(0, offsetPosition);
                end = etsText.substring(offsetPosition);
            } else {
                MethodBlockLocation temp = abilityBlockLocation("export default class");
                if (temp.isEmpty()) {
                    return null;
                }
                start = etsText.substring(0, temp.getEndPosition() - 1);
                end = etsText.substring(temp.getEndPosition() - 1);
            }

        } else {

            switch (position) {
                case START -> {
                    start = etsText.substring(0, location.getStartPosition());
                    end = etsText.substring(location.getStartPosition());
                }
                case END -> {
                    start = etsText.substring(0, location.getEndPosition());
                    end = etsText.substring(location.getEndPosition());
                }
            }

        }
        newContent = start + "\n" + code + "\n" + end;
        return newContent;
    }

    /**
     * 获取Ability所在的位置，
     *
     * @param abilityPrefix ability前缀，目前使用的是“export default class”，在Ability文件中只能有一个，否则会出现编译问题
     * @return Ability类所在的位置，未找到则返回（-1，-1）
     */
    public MethodBlockLocation abilityBlockLocation(String abilityPrefix) {
        MethodBlockLocation location = new MethodBlockLocation(-1, -1);

        int position = etsText.indexOf(abilityPrefix);
        if (position == -1) {
            return location;
        }
        int startPosition = findMethodBlockStartPosition(etsText.substring(position)) + position;
        int endPosition = findMethodBlockEndPosition(etsText.substring(startPosition), 0) + startPosition;

        location.setStartPosition(startPosition + 1);
        location.setEndPosition(endPosition);
        return location;
    }

    /**
     * 方法体所在的位置
     *
     * @param methodName 需要查找的方法名
     * @return 方法体所在的位置，未找到则返回（-1，-1）
     */
    public MethodBlockLocation methodBlockPosition(String methodName) {
        MethodBlockLocation location = new MethodBlockLocation(-1, -1);

        int position = etsText.indexOf(methodName);
        if (position == -1) {
            return location;
        }
        boolean isMatch = false;
        int startPosition = 0;
        String methodInfo = "";
        // 如果有多个匹配到的方法名（比如注释、方法调用），则逐个遍历，找到方法定义的位置，
        while (position != -1) {
            startPosition = findMethodBlockStartPosition(etsText.substring(position)) + position;
            methodInfo = etsText.substring(position, startPosition);
            Pattern pattern = Pattern.compile(ETSMethodInfo.METHOD_PATTERN);
            Matcher mather = pattern.matcher(methodInfo);
            if (mather.matches()) {
                isMatch = true;
                break;
            }
            position = etsText.indexOf(methodName, position + 1);
        }
        if (!isMatch) {
            return location;
        }
        int endPosition = findMethodBlockEndPosition(etsText.substring(startPosition), 0) + startPosition;
        // 根据方法名获取到返回值类型，如果不是void，则需要处理return的位置
        String returnClass = methodInfo.substring(methodInfo.lastIndexOf(":") + 1);
        if (!returnClass.trim().equals(KEY_VOID)) {
            String blockText = etsText.substring(startPosition, endPosition);
            endPosition = blockText.lastIndexOf(KEY_RETURN) + startPosition;
        }

        location.setStartPosition(startPosition + 1);
        location.setEndPosition(endPosition);
        return location;
    }

    /**
     * 查找方法名的起始位置，从方法名开始，查找最近的一个{
     *
     * @param content 文本内容
     * @return 方法的起始位置
     */
    private int findMethodBlockStartPosition(String content) {
        int startPosition = -1;
        for (int i = 0; i < content.length(); i++) {
            char currentChar = content.charAt(i);
            if (currentChar == '{') {
                startPosition = i;
                break;
            }
        }
        return startPosition;
    }

    /**
     * 查找方法名的结束位置，根据方法名后第一个{的位置，获取其对应的}的位置
     *
     * @param content 文本内容
     * @return 方法的结束位置
     */
    private int findMethodBlockEndPosition(String content, int startPosition) {
        int endPosition = -1;
        Stack<Integer> stack = new Stack<>();

        for (int i = 0; i < content.length(); i++) {
            char currentChar = content.charAt(i);
            if (currentChar == '{') {
                stack.push(i);
            } else if (currentChar == '}') {
                if (!stack.isEmpty()) {
                    int openingBraceIndex = stack.pop();
                    if (openingBraceIndex == startPosition) {
                        endPosition = i;
                        break;
                    }
                }
            }
        }

        return endPosition;
    }

}
